package ru.averta.notes.service.security.token;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.averta.notes.other.UtilsApi;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * <code>InvalidateSessionFilter</code>
 *
 * @author fedor.belov (fedor.belov@mail.ru)
 *         Date: 02.09.11 18:19
 */
public class InvalidateSessionFilter implements Filter {

    private Logger logger = LoggerFactory.getLogger(InvalidateSessionFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    /**
     * При обработке запроса к API сессия не должна использоваться
     * Чтобы выключить сессию только для запросов к API, оборачиваем запрос классом, который не возвращает сессию
     *
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        if (UtilsApi.isApiRequestWithoutSession((HttpServletRequest) request)) {
            //Очищаем сессию, чтобы пользователь не зашел по закешированной информации
            //Данный подход неверен, т.к. у пользователя может быть просто открыт сайт с сессией
            /*HttpSession session = ((HttpServletRequest) request).getSession(false);
            if (session != null) session.invalidate();*/

            //Подменяем запрос, чтобы не создавать сессию
            request = new HttpApiRequest((HttpServletRequest) request);
        }

        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }

    /**
     * Класс оборачивает запрос, чтобы не возвращать объект сессии
     */
    public class HttpApiRequest extends HttpServletRequestWrapper {

        /**
         * Constructs a request object wrapping the given request.
         *
         * @throws IllegalArgumentException if the request is null
         */
        public HttpApiRequest(HttpServletRequest request) {
            super(request);
        }

        @Override
        public HttpSession getSession(boolean create) {
            logger.trace("API: Попытка получить / создать сессию");
            return null;
        }

        @Override
        public HttpSession getSession() {
            logger.error("API: Попытка получить существующую сессию и, если она не существует, создать ее!");
            throw new CantCreateSessionException();
        }
    }

    public class CantCreateSessionException extends RuntimeException {

    }

}
